#ifndef  _MSG_FACTOR_H_
#define  _MSG_FACTOR_H_
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include<iostream>
#include"string.h"
#include"../../api/api.h"

//#include "../connection/wsConnection.h"
using namespace std;
using namespace rapidjson;
	
typedef asrMsg *        sMsg;//since we need release it by hand, so just do not use shared_ptr
typedef void (*cbReporter) (void *, const char*);
typedef int (*cbFunc) (void* pCbObj, asrMsg* pMsg, int iIsFinal);

namespace speech
{
class msgFactory
{		
public:
	msgFactory(cbFunc pCbFunc, void* pCbObj)
		:_pMsg(NULL),
		_pCbFunc(pCbFunc),
		_pCbObj(pCbObj)
	{}
	~msgFactory()
	{
		if(_pMsg)
		{
		
			if(_pMsg->_pAsrRes)
			{
				if(_pMsg->_pAsrRes->_pRes)
				    delete [] _pMsg->_pAsrRes->_pRes;
				free( _pMsg->_pAsrRes);
			}
			free(_pMsg);
			_pMsg = NULL;
		}
	}
	sMsg createMsg(int iIndex,int iMsgType)
	{
		_pMsg = (asrMsg*)malloc(sizeof(asrMsg));
		memset(_pMsg,0,sizeof(asrMsg));
		if (RECO_CB_DATA == iMsgType)
		{
			_pMsg->_pAsrRes = (asrRes*) malloc(sizeof(asrRes));
			memset(_pMsg->_pAsrRes,0,sizeof(asrRes));
			_pMsg->_pAsrRes->_iIndex = iIndex;
		}
		_pMsg->_iCommand = iMsgType;
		return _pMsg;
	}
	void setBeginTime(int iBeginTime)
	{
		assert(_pMsg->_pAsrRes);	
		_pMsg->_pAsrRes->_iBeginTime = iBeginTime;
	}
	void setFileName(const char* pFileName, int iLen)
	{
		strncpy(_pMsg->_pAsrRes->_file,pFileName,iLen);
	}
	void updateEndTime(int iEndTime)
	{
		assert(_pMsg->_pAsrRes);
		_pMsg->_pAsrRes->_iEndTime = iEndTime;
	}
	sMsg getMsg()
	{
		return _pMsg;
	}
	int processMsg(const char* pMsg)
	{
		Document d;
		d.Parse(pMsg);
		Value& code = d["code"];
		
		if (code.GetInt() == 0)
		{
			Value& s = d["data"]["result"]["ws"];
			Value& status = d["data"]["status"];
			int iStatus = status.GetInt();
			std::string finalRes;
			for (unsigned int i = 0; i < s.Size(); ++i)
			{
				Value& elem = s[i]["cw"];
				for(unsigned int j = 0; j < elem.Size(); ++j)
					finalRes +=std::string(elem[j]["w"].GetString());
			}
			//std::cout << "Final res " << finalRes <<  std::endl;
			int iLen = strlen(finalRes.c_str());
			if(_pMsg->_pAsrRes->_pRes == NULL)
			{
				_pMsg->_pAsrRes->_pRes = new char[iLen +1];
				_pMsg->_pAsrRes->_iResLen = iLen;
				strncpy(_pMsg->_pAsrRes->_pRes,finalRes.c_str(),iLen);
				_pMsg->_pAsrRes->_pRes[iLen]='\0';
			}
			else
			{
				int iStrLen = iLen + strlen(_pMsg->_pAsrRes->_pRes) ;
				char* allRes = new char[iStrLen + 1];
				strncpy(allRes,_pMsg->_pAsrRes->_pRes, strlen(_pMsg->_pAsrRes->_pRes));
				strncpy(allRes+strlen(_pMsg->_pAsrRes->_pRes),finalRes.c_str(),iLen);
				allRes[iStrLen]='\0';
				delete [] _pMsg->_pAsrRes->_pRes ;
				_pMsg->_pAsrRes->_pRes = allRes;
				_pMsg->_pAsrRes->_iResLen = iStrLen;
			}
			cbFunc  f =getCbFunc();
			(*f)(getCbObj(),_pMsg,1);
			//need release memory in sMsg
			char forPrint[10240];
			sprintf(forPrint,"Get res %s",finalRes.c_str());
#ifdef LOGFILE
			log::getInstance()->getLog()->info(forPrint);
#else
			printf("%s\n",forPrint);
#endif
			return iStatus;
		}
		else
		{
			Value& errMsg = d["message"];
			std::cout << "code is" << code.GetInt() << "err is " << errMsg.GetString() ;
		}
		return 0;
	}	
    cbFunc getCbFunc()
	{
		return _pCbFunc;
	}
	void* getCbObj()
	{
		return _pCbObj;
	}
private:
	asrMsg*      _pMsg;
	cbFunc                       _pCbFunc;
	void*                        _pCbObj;
};

}
#endif
